<template>
  <div class="InventoryQuery">
    <div class="InventoryQuery-Toolbar">
      <el-form :model="form" label-width="100px" class="InventoryQuery-Form" inline>
        <el-form-item label="模式" prop="mode">
          <el-radio-group v-model="form.mode" @change="handleModeChange">
            <el-radio-button label="year">年</el-radio-button>
            <el-radio-button label="month">月</el-radio-button>
            <el-radio-button label="day">日</el-radio-button>
          </el-radio-group>
        </el-form-item>
        <template v-if="form.mode==='year'">
          <el-form-item label="年份范围" required>
            <div class="InventoryQuery-Range">
              <el-select v-model="yearRange.start" placeholder="开始年" class="InventoryQuery-RangeSelect"
                         @change="validateYearRange">
                <el-option v-for="y in yearOptions" :key="y" :label="y" :value="y"/>
              </el-select>
              <span class="InventoryQuery-RangeSep">-</span>
              <el-select v-model="yearRange.end" placeholder="结束年" class="InventoryQuery-RangeSelect"
                         @change="validateYearRange">
                <el-option v-for="y in yearOptions" :key="'e'+y" :label="y" :value="y"/>
              </el-select>
            </div>
          </el-form-item>
        </template>
        <template v-else-if="form.mode==='month'">
          <el-form-item label="月份范围" required>
            <el-date-picker v-model="monthRange" type="monthrange" range-separator="至" start-placeholder="开始月份"
                            end-placeholder="结束月份" value-format="YYYY-MM" :disabled-date="disableFutureMonth"
                            :clearable="false" :editable="false" @change="validateMonthRange"/>
          </el-form-item>
        </template>
        <template v-else>
          <el-form-item label="日期范围" required>
            <el-date-picker v-model="dayRange" type="daterange" range-separator="至" start-placeholder="开始日期"
                            end-placeholder="结束日期" value-format="YYYY-MM-DD" :disabled-date="disableFutureDay"
                            :clearable="false" :editable="false" :shortcuts="dayShortcuts" @change="validateDayRange"/>
          </el-form-item>
        </template>
        <el-form-item label="商品" required>
          <div class="InventoryQuery-ProductSelect">
            <template v-if="selectedProduct">
              <div class="InventoryQuery-ProductSelectInfo">
                <span class="InventoryQuery-ProductSelectCode">{{ selectedProduct.code }}</span>
                <span class="InventoryQuery-ProductSelectName">{{ selectedProduct.name }}</span>
              </div>
              <el-button type="primary" link @click="openProductDialog">重选</el-button>
              <el-button type="danger" link @click="clearProduct">清除</el-button>
            </template>
            <template v-else>
              <el-button type="primary" @click="openProductDialog">选择商品</el-button>
            </template>
          </div>
        </el-form-item>
      </el-form>
      <div class="InventoryQuery-Actions">
        <el-button type="primary" :disabled="!selectedProduct" @click="handleQuery">查询</el-button>
        <el-button @click="handleReset">重置</el-button>
      </div>
    </div>

    <div class="InventoryQuery-ChartWrapper" v-if="chartData.length" :class="{ 'is-loading': loading }">
      <div v-if="loading" class="InventoryQuery-ChartLoading">加载中...</div>
      <div v-else ref="chartRef" class="InventoryQuery-Chart"></div>
    </div>
    <div v-else class="InventoryQuery-Placeholder">请选择模式、时间范围并选择商品后点击查询，显示库存变化</div>

    <ProductSelectDialog v-model:visible="productDialogVisible" @selected="handleProductSelected"/>
  </div>
</template>

<script setup>
import {ref, reactive, watch, onMounted, onBeforeUnmount, nextTick} from 'vue'
import {ElMessage} from 'element-plus'
import * as echarts from 'echarts'
import ProductSelectDialog from '../../../components/ProductSelectDialog.vue'
import {listInventoryChanges} from '../../../api/inventoryDetailApi.js'

// 表单与范围
const form = reactive({mode: 'day'})
const currentYear = new Date().getFullYear()
const yearOptions = Array.from({length: 50}).map((_, i) => currentYear - i)
const yearRange = reactive({start: currentYear - 4, end: currentYear})
const monthRange = ref([])
const dayRange = ref([])

// 商品
const selectedProduct = ref(null)
const productDialogVisible = ref(false)
const openProductDialog = () => {
  productDialogVisible.value = true
}
const handleProductSelected = (p) => {
  productDialogVisible.value = false;
  if (p) selectedProduct.value = p
}
const clearProduct = () => {
  selectedProduct.value = null
}

// 快捷日期
const dayShortcuts = [
  {
    text: '近7天', value: () => {
      const end = new Date();
      const start = new Date(end.getTime() - 6 * 86400000);
      return [formatDate(start), formatDate(end)]
    }
  },
  {
    text: '近30天', value: () => {
      const end = new Date();
      const start = new Date(end.getTime() - 29 * 86400000);
      return [formatDate(start), formatDate(end)]
    }
  }
]

// 限制未来
const disableFutureMonth = (d) => {
  if (!d) return false;
  const now = new Date();
  const diff = (d.getFullYear() - now.getFullYear()) * 12 + (d.getMonth() - now.getMonth());
  return diff > 6
}
const disableFutureDay = (d) => {
  if (!d) return false;
  const now = new Date();
  const max = new Date(now.getTime() + 30 * 86400000);
  return d.getTime() > max.getTime()
}

// 工具
const formatDate = (d) => {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${y}-${m}-${day}`
}
const initMonthRange = () => {
  monthRange.value = [`${currentYear}-01`, `${currentYear}-12`]
}
const initDayRange = () => {
  const end = new Date();
  const start = new Date(end.getTime() - 6 * 86400000);
  dayRange.value = [formatDate(start), formatDate(end)]
}

// 校验
const validateYearRange = () => {
  if (yearRange.start > yearRange.end) yearRange.end = yearRange.start;
  const span = yearRange.end - yearRange.start + 1;
  if (span > 24) {
    yearRange.start = yearRange.end - 23;
    ElMessage.warning('年份跨度不能超过 24 年')
  }
}
const validateMonthRange = () => {
  if (!monthRange.value || monthRange.value.length !== 2) return;
  const [s, e] = monthRange.value;
  const [sy, sm] = s.split('-').map(Number);
  const [ey, em] = e.split('-').map(Number);
  let diff = (ey - sy) * 12 + (em - sm) + 1;
  if (diff > 24) {
    ElMessage.warning('月份跨度不能超过 24 个月');
    const date = new Date(s + '-01');
    date.setMonth(date.getMonth() + 23);
    const ny = date.getFullYear();
    const nm = String(date.getMonth() + 1).padStart(2, '0');
    monthRange.value = [s, `${ny}-${nm}`]
  }
}
const validateDayRange = () => {
  if (!dayRange.value || dayRange.value.length !== 2) return;
  const [s, e] = dayRange.value;
  const diffDays = (new Date(e) - new Date(s)) / 86400000 + 1;
  if (diffDays > 60) {
    ElMessage.warning('日期跨度不能超过 60 天');
    const end = new Date(e);
    const start = new Date(end.getTime() - 59 * 86400000);
    dayRange.value = [formatDate(start), formatDate(end)]
  }
}

// 条件
const getLastDayOfMonth = (y, m) => new Date(y, m, 0).getDate()
const buildCondition = () => {
  if (form.mode === 'year') return {
    mode: 'year',
    startDate: `${yearRange.start}-01-01`,
    endDate: `${yearRange.end}-12-31`,
    yearRange: {start: yearRange.start, end: yearRange.end}
  }
  if (form.mode === 'month') {
    const [s, e] = monthRange.value || [];
    if (!s || !e) return null;
    const [ey, em] = e.split('-').map(Number);
    const endDay = getLastDayOfMonth(ey, em);
    return {
      mode: 'month',
      startDate: `${s}-01`,
      endDate: `${e}-${String(endDay).padStart(2, '0')}`,
      monthRange: {start: s, end: e}
    }
  }
  const [ds, de] = dayRange.value || [];
  if (!ds || !de) return null;
  return {mode: 'day', startDate: ds, endDate: de}
}

// 数据
const chartData = ref([]) // {label,quantity,change,operationType}
const unitRef = ref('')
const loading = ref(false)
let chartInstance = null
const chartRef = ref(null)

// 查询
const handleQuery = async () => {
  if (!selectedProduct.value) return ElMessage.error('请选择商品')
  if (form.mode === 'year') validateYearRange(); else if (form.mode === 'month') {
    validateMonthRange();
    if (!monthRange.value || monthRange.value.length !== 2) return ElMessage.error('请选择月份范围')
  } else {
    validateDayRange();
    if (!dayRange.value || dayRange.value.length !== 2) return ElMessage.error('请选择日期范围')
  }
  const condition = buildCondition();
  if (!condition) return
  const payload = {...condition, productId: selectedProduct.value.id}
  loading.value = true
  chartData.value = []
  disposeChart()
  try {
    const res = await listInventoryChanges(payload)
    const list = (res && res.list) || []
    unitRef.value = res && res.unit ? res.unit : ''
    if (!Array.isArray(list) || !list.length) {
      ElMessage.info('该时段无库存变动');
      return
    }
    // 直接使用返回的第一个变化节点作为起点（不补 baseline）
    chartData.value = list.map(it => ({
      label: it.time,
      quantity: it.quantity,
      change: it.change,
      operationType: it.operationType
    }))
  } catch (e) {
    ElMessage.error('查询失败')
  } finally {
    loading.value = false
  }
}

// 重置
const handleReset = () => {
  form.mode = 'day'
  yearRange.start = currentYear - 4;
  yearRange.end = currentYear
  initMonthRange();
  initDayRange();
  selectedProduct.value = null
  chartData.value = [];
  disposeChart()
}

// 模式切换
const handleModeChange = () => {
  if (form.mode === 'year') {
    yearRange.start = currentYear - 4;
    yearRange.end = currentYear
  } else if (form.mode === 'month') initMonthRange(); else initDayRange()
  chartData.value = [];
  disposeChart()
}

// 监听
watch(chartData, async v => {
  if (!v.length) return;
  await nextTick();
  renderChart()
})

// 映射
const opColorMap = {
  purchase: '#3478f6',
  sales: '#d03050',
  damage: '#999999',
  overflow: '#1a7f37',
  other: '#e6a23c',
  red_purchase: '#88b6ff',
  red_sales: '#ff8fa0'
}
const opLabelMap = {
  purchase: '采购',
  sales: '销售',
  damage: '报损',
  overflow: '报溢',
  other: '其他',
  red_purchase: '采购红冲',
  red_sales: '销售红冲'
}

// 图表
const renderChart = () => {
  if (!chartRef.value) return
  if (!chartInstance) {
    chartInstance = echarts.init(chartRef.value);
    window.addEventListener('resize', handleResize)
  }
  const x = chartData.value.map(i => i.label)
  const y = chartData.value.map(i => i.quantity)
  const same = y.length > 0 && y.every(v => v === y[0])
  const yMin = same ? y[0] - 1 : null
  const yMax = same ? y[0] + 1 : null
  const unit = unitRef.value
  chartInstance.setOption({
    tooltip: {
      trigger: 'axis',
      formatter: ps => ps.map(p => {
        const it = chartData.value[p.dataIndex];
        return `${p.axisValue}<br/>操作: ${opLabelMap[it.operationType] || '-'}<br/>变动: ${formatSigned(it.change)} ${unit}<br/>库存: ${formatQty(it.quantity)} ${unit}`
      }).join('')
    },
    grid: {left: 50, right: 20, top: 40, bottom: 60},
    xAxis: {type: 'category', data: x, boundaryGap: false, axisLabel: {rotate: x.length > 6 ? 30 : 0}},
    yAxis: {type: 'value', name: unit ? `库存(${unit})` : '库存', min: yMin, max: yMax},
    series: [{
      name: '库存',
      type: 'line',
      step: 'end',
      data: y,
      showSymbol: true,
      smooth: false,
      itemStyle: {
        color: (params) => {
          const op = chartData.value[params.dataIndex].operationType
          return opColorMap[op] || '#409EFF'
        }
      },
      lineStyle: {color: '#409EFF'},
      areaStyle: {opacity: 0.05}
    }]
  })
  chartInstance.resize()
}
const handleResize = () => {
  chartInstance && chartInstance.resize()
}
const disposeChart = () => {
  if (chartInstance) {
    window.removeEventListener('resize', handleResize)
    chartInstance.dispose()
    chartInstance = null
  }
}

// 格式化
const formatQty = v => (v == null || v === '' ? '0.00' : Number(v).toFixed(2))
const formatSigned = v => {
  if (v == null || v === '') return '0.00'
  const n = Number(v)
  return (n > 0 ? '+' : '') + n.toFixed(2)
}

onMounted(() => {
  initMonthRange()
  initDayRange()
})

onBeforeUnmount(() => {
  disposeChart()
})
</script>

<style scoped lang="scss">
.InventoryQuery {
  &-Toolbar {
    padding: 16px 0;
    border-bottom: 1px solid #eee;
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  &-Form {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: flex-start;
  }

  &-Actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
  }

  &-Range {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  &-RangeSelect {
    width: 120px;
  }

  &-RangeSep {
    color: #606266;
  }

  &-ProductSelect {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 260px;
  }

  &-ProductSelectInfo {
    display: flex;
    gap: 8px;
    font-size: 14px;
    color: #303133;
  }

  &-ProductSelectCode {
    font-weight: 600;
  }

  &-ProductSelectName {
    max-width: 160px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  &-ChartWrapper {
    padding: 16px 0;
    position: relative;
  }

  &-Chart {
    width: 100%;
    height: 420px;
  }

  &-ChartLoading {
    position: absolute;
    inset: 0;
    background: rgba(255, 255, 255, .75);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    color: #606266;
    border: 1px solid #ebeef5;
  }

  &-Placeholder {
    padding: 32px 0;
    text-align: center;
    color: #909399;
    font-size: 14px;
  }
}
</style>
